using System;
using System.Collections.Generic;
using Xunit;
using FrameIdentityReq.Frames;
using Exceptions;
using System.Text;

namespace xUnitTest
{
    public class TestFrameIdentityReq : IdentityReqFrame
    {
        public TestFrameIdentityReq() : base()
        {
            FactoryCode.Value = 4;
            HardwareSerialNum.Value = "5678";
            UserName.Value = "ljt";
            PWD.Value = "asdfg";
        }

        [Fact]
        public void Test1()
        {
            Assert.Equal(85, Buffer.Count);
            Assert.Equal(3 * 8, HardwareSerialNum.Index);
            Assert.Equal(16 * 8, HardwareSerialNum.Count);
            Assert.Equal(19 * 8, UserName.Index);
            Assert.Equal(32 * 8, UserName.Count);
            Assert.Equal(51 * 8, PWD.Index);
            Assert.Equal(32 * 8, PWD.Count);
            Assert.Equal(83 * 8, CRC.Index);
            Assert.Equal(2 * 8, CRC.Count);

            // 与原版对比
            byte[] originalIdentityReqFrame = UDP_IDENTITY_REQFrame("5678");
            Assert.NotEqual(Buffer, originalIdentityReqFrame);
            CRC.Value = CalculationCRC();
            Assert.Equal(Buffer, originalIdentityReqFrame);

            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("ljt", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            HardwareSerialNum.Value = "";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("", HardwareSerialNum.Value);
            Assert.Equal("ljt", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            HardwareSerialNum.Value = "1234567890";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890", HardwareSerialNum.Value);
            Assert.Equal("ljt", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            HardwareSerialNum.Value = "1234567890123456";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("ljt", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            // HardwareSerialNum = "测试中文";
            // Assert.True(Length == 85);
            // Assert.True(ProtocolVersion == 4);
            // Assert.True(FactoryCode == 4);
            // Assert.True(InfoLength == 64);
            // Assert.True(HardwareSerialNum == "测试中文");
            // Assert.True(UserName == "ljt");
            // Assert.True(PWD == "asdfg");

            Assert.Throws<ExceptionOverLength>(() => HardwareSerialNum.Value = "12345678901234567");

            UserName.Value = "";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            UserName.Value = "1234567890";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("1234567890", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            UserName.Value = "12345678901234567890123456789012";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("asdfg", PWD.Value);

            Assert.Throws<ExceptionOverLength>(() => UserName.Value = "123456789012345678901234567890123");

            PWD.Value = "";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("", PWD.Value);

            PWD.Value = "";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("", PWD.Value);

            PWD.Value = "1234567890";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("1234567890", PWD.Value);

            PWD.Value = "12345678901234567890123456789012";
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("12345678901234567890123456789012", PWD.Value);

            Assert.Throws<ExceptionOverLength>(() => PWD.Value = "123456789012345678901234567890123");

            CRC.Value = 0;
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("12345678901234567890123456789012", PWD.Value);
            Assert.Equal(0, CRC.Value);

            CRC.Value = 0xFFFF;
            Assert.Equal(4, ProtocolVersion.Value);
            Assert.Equal(4, FactoryCode.Value);
            Assert.Equal(64, InfoLength.Value);
            Assert.Equal("1234567890123456", HardwareSerialNum.Value);
            Assert.Equal("12345678901234567890123456789012", UserName.Value);
            Assert.Equal("12345678901234567890123456789012", PWD.Value);
            Assert.Equal(0XFFFF, CRC.Value);

            IList<byte> buffer = Buffer;
            Assert.Equal(85, buffer.Count);
            Assert.Equal((UInt16)((buffer[buffer.Count - 2] << 8) + buffer[buffer.Count - 1]), CRC.Value);

        }


        /// <summary>
        /// 原版代码
        /// </summary>
        /// <param name="hardwareserialnum"></param>
        /// <returns></returns>s
        private byte[] UDP_IDENTITY_REQFrame(string hardwareserialnum)//身份验证请求帧
        {
            byte[] udpsendbuf = new byte[85];
            UInt16 UDP_IDENTITY_REQ = 0;
            byte MCODE = 0x44;


            for (int i = 0; i < udpsendbuf.Length; i++)
            {
                udpsendbuf[i] = 0;
            }
            udpsendbuf[0] = MCODE;//高4bit为协议版本，固定为0x04；低4bit为厂家代码，0-3保留，4～15用于区分不同厂家

            UInt16 stemp = UDP_IDENTITY_REQ;
            stemp = (UInt16)(stemp << 11);  //帧类型 ，占5bit 高字节
            stemp += 64;                    //数据长度,32字节的用户名和32字节的密码
            udpsendbuf[2] = (byte)stemp;    //信息长度 64，占11bit
            stemp = (UInt16)(stemp >> 8);
            udpsendbuf[1] = (byte)stemp;

            //byte[] hardwareID = uartanalys.strToToHexByte(basicpara.hardwareserialnum);
            //for (int i = 0; i < 16; i++)//固定16个字节
            //{
            //    udpsendbuf[3 + i] = hardwareID[i];
            //}
            // byte[] arrByte1 = System.Text.Encoding.GetEncoding("GB2312").GetBytes(hardwareserialnum);
            byte[] arrByte1 = System.Text.Encoding.ASCII.GetBytes(hardwareserialnum);
            arrByte1.CopyTo(udpsendbuf, 3);//定义设备代码占用16字节,16Bytes在身份验证请求时使用，其余情况下使用3Bytes，3Bytes登录后由服务器分配，作为通信ID

            // byte[] arrByte2 = System.Text.Encoding.GetEncoding("GB2312").GetBytes("ljt");
            byte[] arrByte2 = System.Text.Encoding.ASCII.GetBytes("ljt");
            arrByte2.CopyTo(udpsendbuf, 3 + 16);//用户名占用32字节

            byte[] arrByte3 = System.Text.Encoding.ASCII.GetBytes("asdfg");
            arrByte3.CopyTo(udpsendbuf, 3 + 16 + 32);//密码占用32字节

            UInt16 temp = crc16_calculate(udpsendbuf, 83);//3+16+32+32
            udpsendbuf[84] = (byte)temp; temp = (UInt16)(temp >> 8);
            udpsendbuf[83] = (byte)temp;

            stemp = 85;
            //uartanalys.hex_to_uart_pkt(ref udpsendbuf, ref stemp);
            // Udp_Send(udpsendbuf, stemp);//以太 udp 发送

            return udpsendbuf;
        }

        /// <summary>
        /// 原版代码
        /// </summary>
        /// <param name="pucSendBuf"></param>
        /// <param name="usLen"></param>
        /// <returns></returns>
        public UInt16 crc16_calculate(byte[] pucSendBuf, UInt16 usLen)
        {
            UInt16 usCrc = 0xFFFF;

            for (UInt16 i = 0; i < usLen; i++)
            {
                usCrc ^= (UInt16)pucSendBuf[i];
                for (UInt16 j = 0; j < 8; j++)
                {
                    if ((usCrc & 1) != 0)
                    {
                        usCrc >>= 1;
                        usCrc ^= 0xA001;
                    }
                    else
                    {
                        usCrc >>= 1;
                    }
                }
            }

            return usCrc;
        }

    }
}